package com.szh.gateway.exec;


import cn.dev33.satoken.exception.IdTokenInvalidException;
import cn.dev33.satoken.exception.NotLoginException;
import cn.dev33.satoken.exception.NotPermissionException;
import cn.dev33.satoken.exception.SaTokenException;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.szh.common.resp.Resp;
import org.springframework.boot.web.reactive.error.ErrorWebExceptionHandler;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.annotation.Order;
import org.springframework.core.io.buffer.DataBufferFactory;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.http.server.reactive.ServerHttpResponse;
import org.springframework.web.server.ServerWebExchange;
import reactor.core.publisher.Mono;

@Order(-1) // 保证优先级低于默认的ResponseStatusExceptionHandler,这样能拿到响应状态码
@Configuration
public class GlobalErrorExceptionHandler implements ErrorWebExceptionHandler {
    private final ObjectMapper objectMapper = new ObjectMapper();

    @Override
    public Mono<Void> handle(ServerWebExchange exchange, Throwable ex) {
        ServerHttpResponse response = exchange.getResponse();
        if (response.isCommitted()) {
            return Mono.error(ex);
        }
        // 将返回格式设为JSON
        response.getHeaders().setContentType(MediaType.APPLICATION_JSON);
        if (ex.getCause() !=null){
            ex = ex.getCause();
        }
        if (ex instanceof NotLoginException || ex instanceof IdTokenInvalidException){
            response.setStatusCode(HttpStatus.UNAUTHORIZED);
        }
        else if (ex instanceof NotPermissionException){
            response.setStatusCode(HttpStatus.FORBIDDEN);
        }
        else if (ex instanceof SaTokenException){
            response.setStatusCode(HttpStatus.UNAUTHORIZED);
        }else {
            response.setStatusCode(HttpStatus.INTERNAL_SERVER_ERROR);
        }
        // 改变请求响应返回行为
        Throwable finalEx = ex;
        return response.writeWith(Mono.fromSupplier(() -> {
            DataBufferFactory bufferFactory = response.bufferFactory();
            Resp<Object> errorResult = Resp.builder().data(null).code(String.valueOf(response.getStatusCode().value())).message(finalEx.getMessage()).build();
            try {
                // 返回ErrorResult
                return bufferFactory.wrap(objectMapper.writeValueAsBytes(errorResult));
            } catch (JsonProcessingException e) {
                e.printStackTrace();
                return bufferFactory.wrap(new byte[0]);
            }
        }));
    }

}
